﻿@page "/filemanager"
@using System.IO
@using System.Text
@using System.Web
@using System.Drawing;
@inject Microsoft.AspNetCore.Hosting.IWebHostEnvironment HostEnvironment

@if (UserIsAnAdmin)
{
    <h1>File Manager</h1>
    <br />
    <div class="row">
        <RadzenUpload ChooseText="Upload Files" Multiple="true"
                      Accept="image/*"
                      Url=@($"api/upload/multiple?CurrentDirectory={HttpUtility.UrlEncode(CurrentDirectory.ToLower().Replace(CurrentRoot.ToLower(), ""))}")
                      Style="margin-bottom: 20px;height: 45px"
                      Progress="@((args) => OnProgress(args))" />
        <RadzenSplitButton Click="(args) => FolderAction(args)"
                           Text="Folder"
                           ButtonStyle="ButtonStyle.Info"
                           Style="margin-bottom: 20px;height: 35px">
            <ChildContent>
                <RadzenSplitButtonItem Text="Add Folder" Value="Add" />
                <RadzenSplitButtonItem Text="Delete Folder" Value="Delete" />
            </ChildContent>
        </RadzenSplitButton>

        <RadzenButton Disabled="@(SelectedFile.FileName == null)"
                      Text="Delete"
                      Click="DeleteSelectedFile"
                      ButtonStyle="ButtonStyle.Danger"
                      Style="margin-bottom: 20px;height: 35px" />
    </div>
    <div class="row">
        <div class="col-md-4" style="margin-bottom: 16px">
            <RadzenTree Change="@LogChange" Data="@Directories"
                        Expand="@LoadDirectory"
                        Style="width: 100%; height: 300px">
                <RadzenTreeLevel Text="@GetTextForNode"
                                 Template="@FileOrFolderTemplate" />
            </RadzenTree>
        </div>
        <div class="col-md-8" style="margin-bottom: 16px">
            <RadzenDataList @ref="FileDataList" Data="@Files"
                            AllowPaging="true" TItem="FileObject"
                            WrapItems="true" PageSize="6">
                <Template Context="file">
                    <RadzenImage Path="@file.FilePath"
                                 Style="@((file.FileName == SelectedFile.FileName)
                                                          ? $"height:{file.ThumbnailHeight}px;" +
                                                          $"width:{file.ThumbnailWidth}px;" +
                                                          $"padding:10px;background-color:darkgrey;"
                                                          : $"height:{file.ThumbnailHeight}px;" +
                                                          $"width:{file.ThumbnailWidth}px;" +
                                                          $"padding:10px;background-color:white;")"
                                 Click="@((args) => SelectImage(file))" />
                </Template>
            </RadzenDataList>
        </div>
    </div>
}

@if (ShowProgressBarPopup)
{
    <div class="modal" tabindex="-1" style="display:block" role="dialog">
        <div class="modal-dialog modal-sm">
            <div class="modal-content">
                <div class="modal-header">
                    <h4 class="modal-title">Upload Status</h4>
                </div>
                <div align="center">
                    <RadzenProgressBar Value="@progress"
                                       Unit="@info"
                                       Visible="@(progress > 0)"
                                       Style="margin-bottom: 20px" />
                </div>
            </div>
        </div>
    </div>
}

@if (ShowFolderPopup)
{
    <div class="modal" tabindex="-1" style="display:block" role="dialog">
        <div class="modal-dialog modal-sm">
            <div class="modal-content">
                <div class="modal-header">
                    <h4 class="modal-title">New Folder Name</h4>
                    <button type="button" class="close"
                            @onclick="CloseFolderPopup">
                        <span aria-hidden="true">X</span>
                    </button>
                </div>
                <div align="center">
                    <RadzenTextBox Placeholder="Folder Name"
                                   @bind-Value="NewFolderName"
                                   Style="margin-bottom: 20px" />
                    <RadzenButton Text="Add Folder"
                                  Click="AddFolderName"
                                  ButtonStyle="ButtonStyle.Success"
                                  Style="margin-bottom: 20px;height: 35px" />
                </div>
            </div>
        </div>
    </div>
}

@code {
    [CascadingParameter]
    private Task<AuthenticationState> authenticationStateTask { get; set; }
    System.Security.Claims.ClaimsPrincipal CurrentUser;

    string ADMINISTRATION_ROLE = "Administrators";
    bool UserIsAnAdmin = false;

    private RadzenDataList<FileObject> FileDataList;
    private bool ShowFileManager = false;
    private bool ShowProgressBarPopup = false;
    private bool ShowFolderPopup = false;
    private int progress;
    private string info;

    private string CurrentDirectory = "";
    private string CurrentRoot = "";
    private string NewFolderName = "";
    private FileObject SelectedFile = new FileObject();
    private List<string> Directories = new List<string>();
    private List<FileObject> Files = new List<FileObject>();
    private Dictionary<DateTime, string> events =
        new Dictionary<DateTime, string>();

    protected override async Task OnInitializedAsync()
    {
        // Get the current user
        CurrentUser = (await authenticationStateTask).User;

        if (CurrentUser.Identity.IsAuthenticated)
        {
            UserIsAnAdmin = CurrentUser.IsInRole(ADMINISTRATION_ROLE);
        }

        CurrentRoot = Path.Combine(HostEnvironment.WebRootPath, "uploads");
        CurrentDirectory = CurrentRoot;
        Directories.Add(CurrentDirectory);
        LoadFiles();
    }

    public void SetShowFileManager(bool paramSetting)
    {
        ShowFileManager = paramSetting;
    }

    // Files

    private void SelectImage(FileObject file)
    {
        if (SelectedFile.FileName == file.FileName)
        {
            SelectedFile = new FileObject();
        }
        else
        {
            SelectedFile = file;
        }
    }

    private void LogChange(TreeEventArgs args)
    {
        // Get the current directory from the
        // argument passed to the method
        CurrentDirectory = args.Value as string;

        // Set the RadzenDataList to page 1
        FileDataList.FirstPage();

        // Reload the FileDataList
        LoadFiles();
    }

    private string GetTextForNode(object data)
    {
        return Path.GetFileName((string)data);
    }

    private RenderFragment<RadzenTreeItem>
        FileOrFolderTemplate = (context) => builder =>
        {
            string path = context.Value as string;
            bool isDirectory = Directory.Exists(path);

            builder.OpenComponent<RadzenIcon>(0);
            builder.AddAttribute(1,
                "Icon", isDirectory ? "folder" :
                "insert_drive_file");

            if (!isDirectory)
            {
                builder.AddAttribute(2,
                    "Style",
                    "margin-left: 24px");
            }
            builder.CloseComponent();
            builder.AddContent(3, context.Text);
        };

    private void LoadDirectory(TreeExpandEventArgs args)
    {
        CurrentDirectory = args.Value as string;

        // Only get the folders not the files
        args.Children.Data =
            Directory.EnumerateFileSystemEntries(CurrentDirectory)
            .Where(x => !x.Contains("."));

        args.Children.Text = GetTextForNode;
        args.Children.HasChildren =
            (path) => Directory.Exists((string)path);
        args.Children.Template = FileOrFolderTemplate;
    }

    private void LoadFiles()
    {
        Files = new List<FileObject>();
        var FileNames =
            Directory.EnumerateFileSystemEntries(CurrentDirectory)
            .Where(x => x.Contains("."));

        foreach (var item in FileNames)
        {
            using (var image = Image.FromFile(item))
            {
                // Calculate Thumbnail
                int thumbnailHeight = 100;
                int thumbnailWidth = 100;
                double x = image.Height / 100;
                if (x > 0)
                {
                    thumbnailHeight = Convert.ToInt32(image.Height / x);
                    thumbnailWidth = Convert.ToInt32(image.Width / x);
                }

                Files.Add(new FileObject()
                {
                    FileName =
                    Path.GetFileName(item),
                    FilePath =
                    item.Replace(HostEnvironment.WebRootPath, "")
                    .Replace("\\uploads", "uploads"),
                    Height = image.Height,
                    Width = image.Width,
                    ThumbnailHeight = Convert.ToInt32(thumbnailHeight),
                    ThumbnailWidth = Convert.ToInt32(thumbnailWidth)
                });
            }
        }

        // Reset selected file
        SelectedFile = new FileObject();

        // Update UI
        StateHasChanged();
    }

    // Uploading

    private async void OnProgress(UploadProgressArgs args)
    {
        try
        {
            ShowProgressBarPopup = true;
            this.info = $"{args.Loaded} of {args.Total} bytes.";
            this.progress = args.Progress;
            StateHasChanged();
            if (args.Loaded == args.Total)
            {
                // Delay to give files time to be saved
                // before reloading file view
                await LoadFilesAsync();
            }
        }
        catch
        {
            ShowProgressBarPopup = false;
        }
    }

    private async Task LoadFilesAsync()
    {
        int Time = 1;
        while (Time > 0)
        {
            Time--;
            StateHasChanged();
            await Task.Delay(1000);
        }
        ShowProgressBarPopup = false;
        LoadFiles();
    }

    // Deleteing

    private void DeleteSelectedFile()
    {
        string RequestedPath = SelectedFile.FilePath;

        RequestedPath =
            RequestedPath.Replace("\\uploads\\", "uploads\\");

        string path = Path.Combine(
            HostEnvironment.WebRootPath,
            RequestedPath);

        if (File.Exists(path))
        {
            File.Delete(path);

            LoadFiles();
        }
    }

    // Folders

    private void AddFolder()
    {
        ShowFolderPopup = true;
    }

    private void CloseFolderPopup()
    {
        ShowFolderPopup = false;
    }

    private void AddFolderName()
    {
        string path = Path.Combine(
            HostEnvironment.WebRootPath,
            CurrentDirectory,
            NewFolderName);

        if (!Directory.Exists(path))
        {
            Directory.CreateDirectory(path);
            LoadFiles();
        }

        NewFolderName = "";
        ShowFolderPopup = false;
    }

    private void FolderAction(RadzenSplitButtonItem item)
    {
        if (item != null)
        {
            if (item.Value == "Add")
            {
                ShowFolderPopup = true;
            }
            // Delete
            if (item.Value == "Delete")
            {
                string path = Path.Combine(
                    HostEnvironment.WebRootPath,
                    CurrentDirectory);

                if (path.ToLower() != CurrentRoot.ToLower())
                {
                    if (Directory.Exists(path))
                    {
                        Directory.Delete(path, true);

                        CurrentDirectory = Path.Combine(
                            HostEnvironment.WebRootPath,
                            "uploads");

                        LoadFiles();
                    }
                }
            }
        }
    }
}